import CryptoJS from 'crypto-js'
import defaultConfig from '@/config'

/**
 * @description 获取localStorage
 * @param {String} key Storage名称
 * @returns {String}
 */
export function localGet(key: string) {
  try {
    const value = JSON.parse(localStorage.getItem(key) ?? '')
    if (value) {
      let nowTime = new Date().getTime()
      if (nowTime > value.dateTime && value.dateTime !== 0) {
        localStorage.removeItem(key)
        return null
      }
      // 解密
      if (defaultConfig.LS_ENCRYPTION_TYPE === 'AES') {
        value.content = JSON.parse(aesDecrypt(value.content, defaultConfig.LS_ENCRYPTION_KEY))
      }
      return value.content
    }
    return null
  } catch (error) {
    return null
  }
}

/**
 * @description 存储localStorage
 * @param {String} key Storage名称
 * @param {*} value Storage值
 * @returns {void}
 */
export function localSet(key: string, value: any, dateTime: number = 0): void {
  // 加密
  if (defaultConfig.LS_ENCRYPTION_TYPE === 'AES') {
    value = aesEncrypt(JSON.stringify(value), defaultConfig.LS_ENCRYPTION_KEY)
  }
  const cacheValue = {
    content: value,
    datetime: dateTime === 0 ? 0 : new Date().getTime() + dateTime * 1000
  }
  localStorage.setItem(key, JSON.stringify(cacheValue))
}

/**
 * @description 清除localStorage
 * @param {String} key Storage名称
 * @returns {void}
 */
export function localRemove(key: string): void {
  window.localStorage.removeItem(key)
}

/**
 * @description 清除所有localStorage
 * @returns {void}
 */
export function localClear(): void {
  window.localStorage.clear()
}

/**
 * 格式化PHP10位时间戳
 * @param timestamp
 * @param format
 * @returns
 */
export function formatTimestamp(timestamp: number, format: string = 'yyyy-MM-dd HH:mm:ss'): string {
  const date = new Date(timestamp * 1000) // 将秒级时间戳转换为毫秒级
  const year = String(date.getFullYear())
  const month = ('0' + (date.getMonth() + 1)).slice(-2)
  const day = ('0' + date.getDate()).slice(-2)
  const hours = ('0' + date.getHours()).slice(-2)
  const minutes = ('0' + date.getMinutes()).slice(-2)
  const seconds = ('0' + date.getSeconds()).slice(-2)

  return format.replace(/yyyy|MM|dd|HH|mm|ss/g, (matched) => {
    switch (matched) {
      case 'yyyy':
        return year
      case 'MM':
        return month
      case 'dd':
        return day
      case 'HH':
        return hours
      case 'mm':
        return minutes
      case 'ss':
        return seconds
      default:
        return matched
    }
  })
}

// 千分符
export function groupSeparator(num: string): string {
  num = num + ''
  if (!num.includes('.')) {
    num += '.'
  }
  return num
    .replace(/(\d)(?=(\d{3})+\.$)/g, function (_, $1) {
      return $1 + ','
    })
    .replace(/\.$/, '')
}

// MD5加密
export function md5Encode(data: any): string {
  return CryptoJS.MD5(data).toString()
}

// MD5加密
export function base64Encode(data: any): string {
  return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(data))
}

export function base64Decode(cipher: any): string {
  return CryptoJS.enc.Base64.parse(cipher).toString(CryptoJS.enc.Utf8)
}

// AES加密
export function aesEncrypt(
  data: any,
  secretKey: string,
  config: { iv?: string; mode?: keyof typeof CryptoJS.mode; padding?: keyof typeof CryptoJS.pad } = {}
): string {
  if (secretKey.length % 8 !== 0) {
    console.warn('[error]: AES秘钥长度需为8的倍数，否则解密将会失败。')
  }
  const result = CryptoJS.AES.encrypt(data, CryptoJS.enc.Utf8.parse(secretKey), {
    iv: CryptoJS.enc.Utf8.parse(config.iv || ''),
    mode: CryptoJS.mode[config.mode || 'ECB'],
    padding: CryptoJS.pad[config.padding || 'Pkcs7']
  })
  return result.toString()
}

// AES解密
export function aesDecrypt(
  cipher: any,
  secretKey: string,
  config: { iv?: string; mode?: keyof typeof CryptoJS.mode; padding?: keyof typeof CryptoJS.pad } = {}
) {
  const result = CryptoJS.AES.decrypt(cipher, CryptoJS.enc.Utf8.parse(secretKey), {
    iv: CryptoJS.enc.Utf8.parse(config.iv || ''),
    mode: CryptoJS.mode[config.mode || 'ECB'],
    padding: CryptoJS.pad[config.padding || 'Pkcs7']
  })
  return CryptoJS.enc.Utf8.stringify(result)
}
